package com.harmony.pilot.data.service.impl;

import com.harmony.pilot.common.constants.ServiceConstants;
import com.harmony.pilot.common.dto.CodeContext;
import com.harmony.pilot.common.dto.CompletionItem;
import com.harmony.pilot.data.service.Neo4jService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.neo4j.driver.Driver;
import org.neo4j.driver.Record;
import org.neo4j.driver.Result;
import org.neo4j.driver.Session;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * Neo4j服务实现
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class Neo4jServiceImpl implements Neo4jService {
    
    private final Driver neo4jDriver;
    
    @Override
    public List<CompletionItem> queryRelatedSymbols(CodeContext context) {
        log.info("Querying related symbols from Neo4j");
        
        List<CompletionItem> items = new ArrayList<>();
        
        try (Session session = neo4jDriver.session()) {
            // 查询与当前文件相关的函数和类
            String cypher = buildRelatedSymbolsQuery(context);
            
            Result result = session.run(cypher);
            
            while (result.hasNext()) {
                Record record = result.next();
                items.add(convertToCompletionItem(record));
            }
            
            log.info("Found {} related symbols from Neo4j", items.size());
            
        } catch (Exception e) {
            log.error("Failed to query related symbols from Neo4j", e);
        }
        
        return items;
    }
    
    @Override
    public Map<String, Object> queryCallChain(String functionName) {
        log.info("Querying call chain for: {}", functionName);
        
        Map<String, Object> result = new HashMap<>();
        
        try (Session session = neo4jDriver.session()) {
            // 查询函数的调用链
            String cypher = 
                "MATCH path = (f:Function {name: $funcName})-[:CALLS*1..5]->(target:Function) " +
                "RETURN path, target.name as targetName " +
                "LIMIT 50";
            
            Map<String, Object> params = new HashMap<>();
            params.put("funcName", functionName);
            
            Result queryResult = session.run(cypher, params);
            
            List<Map<String, Object>> callChain = new ArrayList<>();
            while (queryResult.hasNext()) {
                Record record = queryResult.next();
                Map<String, Object> node = new HashMap<>();
                node.put("target", record.get("targetName").asString());
                callChain.add(node);
            }
            
            result.put("function", functionName);
            result.put("callChain", callChain);
            result.put("count", callChain.size());
            
        } catch (Exception e) {
            log.error("Failed to query call chain from Neo4j", e);
            result.put("error", e.getMessage());
        }
        
        return result;
    }
    
    @Override
    public Map<String, Object> queryDependencies(String moduleName) {
        log.info("Querying dependencies for: {}", moduleName);
        
        Map<String, Object> result = new HashMap<>();
        
        try (Session session = neo4jDriver.session()) {
            // 查询模块的依赖关系
            String cypher = 
                "MATCH (m:Module {name: $moduleName})-[:DEPENDS_ON]->(dep:Module) " +
                "RETURN dep.name as depName, dep.type as depType " +
                "UNION " +
                "MATCH (m:Module {name: $moduleName})<-[:DEPENDS_ON]-(dependent:Module) " +
                "RETURN dependent.name as depName, dependent.type as depType";
            
            Map<String, Object> params = new HashMap<>();
            params.put("moduleName", moduleName);
            
            Result queryResult = session.run(cypher, params);
            
            List<Map<String, Object>> dependencies = new ArrayList<>();
            while (queryResult.hasNext()) {
                Record record = queryResult.next();
                Map<String, Object> dep = new HashMap<>();
                dep.put("name", record.get("depName").asString());
                dep.put("type", record.get("depType").asString(""));
                dependencies.add(dep);
            }
            
            result.put("module", moduleName);
            result.put("dependencies", dependencies);
            result.put("count", dependencies.size());
            
        } catch (Exception e) {
            log.error("Failed to query dependencies from Neo4j", e);
            result.put("error", e.getMessage());
        }
        
        return result;
    }
    
    /**
     * 构建相关符号查询
     */
    private String buildRelatedSymbolsQuery(CodeContext context) {
        // 查询策略：
        // 1. 同文件中的函数和类
        // 2. 被当前文件引用的函数和类
        // 3. 常用的API函数
        
        String filePath = context.getFilePath();
        if (filePath == null) {
            filePath = "";
        }
        
        return String.format(
            "MATCH (n) " +
            "WHERE n:Function OR n:Class " +
            "AND (n.file CONTAINS '%s' OR n.isPublic = true) " +
            "RETURN n.name as name, n.type as type, n.signature as signature, " +
            "       n.documentation as doc, labels(n)[0] as kind " +
            "LIMIT 50",
            filePath.replace("'", "\\'")
        );
    }
    
    /**
     * 将Neo4j记录转换为CompletionItem
     */
    private CompletionItem convertToCompletionItem(Record record) {
        String name = record.get("name").asString("");
        String type = record.get("type").asString("");
        String signature = record.get("signature").asString("");
        String doc = record.get("doc").asString("");
        String kind = record.get("kind").asString("Function");
        
        String itemKind = switch (kind) {
            case "Class" -> ServiceConstants.KIND_CLASS;
            case "Method" -> ServiceConstants.KIND_METHOD;
            case "Field" -> ServiceConstants.KIND_FIELD;
            case "Namespace" -> ServiceConstants.KIND_NAMESPACE;
            default -> ServiceConstants.KIND_FUNCTION;
        };
        
        return CompletionItem.builder()
                .label(name)
                .kind(itemKind)
                .detail(signature.isEmpty() ? type : signature)
                .documentation(doc)
                .insertText(name)
                .source("neo4j")
                .confidence(0.8)
                .sortOrder(20)
                .build();
    }
}

